/**
 * @file protocol_transport.h
 * @brief 协议传输适配器头文件
 * @details 本文件定义了协议层与传输层的适配接口，使104协议能够使用
 *          统一的传输抽象层，支持多种传输方式。提供协议传输的创建、
 *          连接、断开、发送、接收等核心功能接口。
 * 
 * @author zyb
 * @date 2025-10-20
 * @version 1.0
 */

#ifndef PROTOCOL_TRANSPORT_H
#define PROTOCOL_TRANSPORT_H

#include "../../../../../drivers/net/include/transport_net.h"
#include "../../../../../drivers/net/include/transport_net_config.h"
#include "../../common/types/include/protocol_types.h"

#ifdef __cplusplus
extern "C" {
#endif

/* ==================== 协议传输配置 ==================== */

/**
 * @brief 协议传输配置
 */
typedef struct {
    net_transport_config_t transport_config;    /* 传输配置 */
    uint32_t protocol_timeout;                  /* 协议超时时间(ms) */
    uint32_t retry_count;                       /* 重试次数 */
    bool auto_reconnect;                        /* 自动重连 */
} protocol_transport_config_t;

/* ==================== 协议传输状态 ==================== */

/**
 * @brief 协议传输状态
 */
typedef enum {
    PROTOCOL_TRANSPORT_STATE_IDLE = 0,      /* 空闲状态 */
    PROTOCOL_TRANSPORT_STATE_CONNECTING,    /* 连接中 */
    PROTOCOL_TRANSPORT_STATE_CONNECTED,     /* 已连接 */
    PROTOCOL_TRANSPORT_STATE_DISCONNECTING, /* 断开中 */
    PROTOCOL_TRANSPORT_STATE_ERROR          /* 错误状态 */
} protocol_transport_state_t;

/* ==================== 协议传输统计 ==================== */

/**
 * @brief 协议传输统计信息
 */
typedef struct {
    uint64_t apdu_sent;                     /* 发送的APDU数量 */
    uint64_t apdu_received;                 /* 接收的APDU数量 */
    uint64_t bytes_sent;                    /* 发送字节数 */
    uint64_t bytes_received;                /* 接收字节数 */
    uint64_t send_errors;                   /* 发送错误数 */
    uint64_t receive_errors;                /* 接收错误数 */
    uint64_t timeouts;                      /* 超时次数 */
    uint64_t reconnects;                    /* 重连次数 */
    uint32_t last_error;                    /* 最后错误码 */
} protocol_transport_stats_t;

/* ==================== 协议传输回调函数 ==================== */

/**
 * @brief APDU接收回调函数
 * @param apdu 接收到的APDU
 * @param user_data 用户数据
 */
typedef void (*protocol_apdu_receive_callback_t)(const apdu_t* apdu, void* user_data);

/**
 * @brief 协议状态变化回调函数
 * @param state 新状态
 * @param user_data 用户数据
 */
typedef void (*protocol_transport_state_callback_t)(protocol_transport_state_t state, void* user_data);

/**
 * @brief 协议错误回调函数
 * @param error 错误码
 * @param user_data 用户数据
 */
typedef void (*protocol_error_callback_t)(protocol_error_t error, void* user_data);

/* ==================== 协议传输接口 ==================== */

/**
 * @brief 协议传输句柄
 */
typedef struct protocol_transport* protocol_transport_handle_t;

/**
 * @brief 创建协议传输实例
 * @details 创建协议传输实例，初始化传输层和协议层。
 *          验证配置参数，分配内存，初始化互斥锁，创建传输管理器实例。
 * 
 * @param config 协议传输配置
 * @return 协议传输句柄，失败返回NULL
 * 
 * @note 需要调用者负责销毁返回的句柄
 * @warning 配置参数必须有效，否则创建失败
 * 
 * @see protocol_transport_destroy
 * @see protocol_transport_validate_config
 */
protocol_transport_handle_t protocol_transport_create(const protocol_transport_config_t* config);

/**
 * @brief 销毁协议传输实例
 * @details 销毁协议传输实例，清理相关资源。
 *          如果已连接则先断开连接，销毁传输管理器实例，销毁互斥锁，释放内存。
 * 
 * @param handle 协议传输句柄
 * @return 协议错误码
 * 
 * @note 销毁后句柄将无效，不应再使用
 * @warning 必须确保没有其他线程正在使用该句柄
 * 
 * @see protocol_transport_create
 * @see protocol_transport_disconnect
 */
protocol_error_t protocol_transport_destroy(protocol_transport_handle_t handle);

/**
 * @brief 连接协议传输
 * @details 建立协议传输连接。
 *          检查当前状态，设置连接中状态，调用传输层连接，启动接收线程。
 * 
 * @param handle 协议传输句柄
 * @return 协议错误码
 * 
 * @note 如果已经连接或正在连接中，将返回错误
 * @warning 连接失败时状态将变为错误状态
 * 
 * @see protocol_transport_disconnect
 * @see protocol_transport_get_state
 */
protocol_error_t protocol_transport_connect(protocol_transport_handle_t handle);

/**
 * @brief 断开协议传输
 * @details 断开协议传输连接。
 *          设置断开中状态，停止接收线程，断开传输层连接，设置空闲状态。
 * 
 * @param handle 协议传输句柄
 * @return 协议错误码
 * 
 * @note 如果未连接，将返回错误
 * @warning 断开过程中会等待接收线程结束
 * 
 * @see protocol_transport_connect
 * @see protocol_transport_get_state
 */
protocol_error_t protocol_transport_disconnect(protocol_transport_handle_t handle);

/**
 * @brief 获取协议传输状态
 * @details 获取协议传输的当前状态。
 *          线程安全地获取状态信息。
 * 
 * @param handle 协议传输句柄
 * @return 协议传输状态
 * 
 * @note 如果句柄无效，返回错误状态
 * @warning 返回的状态是调用时刻的快照
 * 
 * @see protocol_transport_state_t
 * @see protocol_transport_get_state_name
 */
protocol_transport_state_t protocol_transport_get_state(protocol_transport_handle_t handle);

/**
 * @brief 发送APDU
 * @details 通过协议传输发送APDU。
 *          检查连接状态，组装APDU为字节流，通过传输层发送，更新统计信息。
 * 
 * @param handle 协议传输句柄
 * @param apdu 要发送的APDU
 * @return 协议错误码
 * 
 * @note 只有在连接状态下才能发送APDU
 * @warning 发送失败时会更新错误统计
 * 
 * @see protocol_transport_receive_apdu
 * @see protocol_transport_get_stats
 */
protocol_error_t protocol_transport_send_apdu(protocol_transport_handle_t handle, const apdu_t* apdu);

/**
 * @brief 接收APDU
 * @details 从协议传输接收APDU。
 *          检查连接状态，从缓冲区解析APDU，移动剩余数据，更新统计信息。
 * 
 * @param handle 协议传输句柄
 * @param apdu 接收APDU的缓冲区
 * @param timeout_ms 超时时间(毫秒)
 * @return 协议错误码
 * 
 * @note 只有在连接状态下才能接收APDU
 * @warning 如果缓冲区无完整APDU，将返回超时错误
 * 
 * @see protocol_transport_send_apdu
 * @see protocol_transport_set_apdu_callback
 */
protocol_error_t protocol_transport_receive_apdu(protocol_transport_handle_t handle, apdu_t* apdu, uint32_t timeout_ms);

/**
 * @brief 设置APDU接收回调
 * @details 设置APDU接收回调函数。
 *          当接收到完整APDU时，将调用此回调函数。
 * 
 * @param handle 协议传输句柄
 * @param callback 回调函数
 * @param user_data 用户数据
 * @return 协议错误码
 * 
 * @note 回调函数在接收线程中调用，需要注意线程安全
 * @warning 回调函数不应执行耗时操作
 * 
 * @see protocol_apdu_receive_callback_t
 * @see protocol_transport_receive_apdu
 */
protocol_error_t protocol_transport_set_apdu_callback(protocol_transport_handle_t handle, 
                                                     protocol_apdu_receive_callback_t callback, 
                                                     void* user_data);

/**
 * @brief 设置状态回调
 * @details 设置协议状态变化回调函数。
 *          当协议传输状态发生变化时，将调用此回调函数。
 * 
 * @param handle 协议传输句柄
 * @param callback 回调函数
 * @param user_data 用户数据
 * @return 协议错误码
 * 
 * @note 回调函数在状态变化时立即调用
 * @warning 回调函数不应执行耗时操作
 * 
 * @see protocol_transport_state_callback_t
 * @see protocol_transport_get_state
 */
protocol_error_t protocol_transport_set_state_callback(protocol_transport_handle_t handle,
                                                      protocol_transport_state_callback_t callback,
                                                      void* user_data);

/**
 * @brief 设置错误回调
 * @details 设置协议错误回调函数。
 *          当协议传输发生错误时，将调用此回调函数。
 * 
 * @param handle 协议传输句柄
 * @param callback 回调函数
 * @param user_data 用户数据
 * @return 协议错误码
 * 
 * @note 回调函数在错误发生时立即调用
 * @warning 回调函数不应执行耗时操作
 * 
 * @see protocol_error_callback_t
 * @see protocol_transport_get_stats
 */
protocol_error_t protocol_transport_set_error_callback(protocol_transport_handle_t handle,
                                                      protocol_error_callback_t callback,
                                                      void* user_data);

/**
 * @brief 获取协议传输统计信息
 * @details 获取协议传输统计信息。
 *          包括发送/接收的APDU数量、字节数、错误次数等。
 * 
 * @param handle 协议传输句柄
 * @param stats 统计信息输出
 * @return 协议错误码
 * 
 * @note 统计信息是线程安全的
 * @warning 统计信息在重置前会一直累加
 * 
 * @see protocol_transport_stats_t
 * @see protocol_transport_reset_stats
 */
protocol_error_t protocol_transport_get_stats(protocol_transport_handle_t handle, protocol_transport_stats_t* stats);

/**
 * @brief 重置协议传输统计信息
 * @details 重置协议传输统计信息。
 *          将所有统计计数器清零。
 * 
 * @param handle 协议传输句柄
 * @return 协议错误码
 * 
 * @note 重置操作是线程安全的
 * @warning 重置后无法恢复之前的统计信息
 * 
 * @see protocol_transport_get_stats
 * @see protocol_transport_stats_t
 */
protocol_error_t protocol_transport_reset_stats(protocol_transport_handle_t handle);

/**
 * @brief 设置协议传输配置
 * @details 设置协议传输配置。
 *          验证配置参数，更新内部配置。
 * 
 * @param handle 协议传输句柄
 * @param config 协议传输配置
 * @return 协议错误码
 * 
 * @note 配置更新是线程安全的
 * @warning 配置参数必须有效，否则设置失败
 * 
 * @see protocol_transport_get_config
 * @see protocol_transport_validate_config
 */
protocol_error_t protocol_transport_set_config(protocol_transport_handle_t handle, const protocol_transport_config_t* config);

/**
 * @brief 获取协议传输配置
 * @details 获取协议传输配置。
 *          线程安全地获取当前配置信息。
 * 
 * @param handle 协议传输句柄
 * @param config 协议传输配置输出
 * @return 协议错误码
 * 
 * @note 获取的配置是调用时刻的快照
 * @warning 输出缓冲区必须足够大
 * 
 * @see protocol_transport_set_config
 * @see protocol_transport_config_t
 */
protocol_error_t protocol_transport_get_config(protocol_transport_handle_t handle, protocol_transport_config_t* config);

/* ==================== 协议传输辅助函数 ==================== */

/**
 * @brief 获取传输类型名称
 * @details 获取传输类型的可读名称。
 *          将传输驱动类型枚举转换为可读的字符串。
 * 
 * @param type 传输类型
 * @return 类型名称字符串
 * 
 * @note 返回的字符串是静态的，不需要释放
 * @warning 无效类型返回"UNKNOWN"
 * 
 * @see transport_driver_type_t
 * @see protocol_transport_get_state_name
 */
const char* protocol_transport_get_type_name(int type);

/**
 * @brief 获取协议传输状态名称
 * @details 获取协议传输状态的可读名称。
 *          将协议传输状态枚举转换为可读的字符串。
 * 
 * @param state 协议传输状态
 * @return 状态名称字符串
 * 
 * @note 返回的字符串是静态的，不需要释放
 * @warning 无效状态返回"UNKNOWN"
 * 
 * @see protocol_transport_state_t
 * @see protocol_transport_get_type_name
 */
const char* protocol_transport_get_state_name(protocol_transport_state_t state);

/**
 * @brief 从配置文件加载网络传输配置
 * @details 从配置文件中加载网络传输配置（IP、端口等），并填充到协议传输配置中
 * 
 * @param config_file 网络配置文件路径，如果为NULL则使用默认路径
 * @param config 协议传输配置输出，其中的transport_config字段将被填充
 * @return 协议错误码
 * 
 * @note 如果配置文件不存在，将使用默认配置
 * @warning 输出配置指针不能为空
 * 
 * @see protocol_transport_config_t
 * @see transport_net_config_load
 */
protocol_error_t protocol_transport_load_net_config(const char* config_file, protocol_transport_config_t* config);

/**
 * @brief 验证协议传输配置
 * @details 验证协议传输配置的有效性。
 *          检查驱动类型、超时时间等关键参数。
 * 
 * @param config 协议传输配置
 * @return 协议错误码
 * 
 * @note 验证失败时返回具体的错误码
 * @warning 配置指针不能为空
 * 
 * @see protocol_transport_config_t
 * @see protocol_transport_create
 */
protocol_error_t protocol_transport_validate_config(const protocol_transport_config_t* config);

#ifdef __cplusplus
}
#endif

#endif /* PROTOCOL_TRANSPORT_H */
